package com.corner.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.corner.common.enums.BatchDetailFailReason;
import com.corner.common.enums.WxApiType;
import com.corner.common.enums.WxBatchDetailState;
import com.corner.common.enums.WxBatchState;
import com.corner.common.exception.GlobalException;
import com.corner.system.config.WxPayConfig;
import com.corner.system.domain.BatchDetails;
import com.corner.system.domain.PayToUserPurseRequest;
import com.corner.system.domain.Subsidy;
import com.corner.system.domain.TransferBatches;
import com.corner.system.mapper.TransferBatchesMapper;
import com.corner.system.service.WxPayService;
import com.corner.system.utils.OrderNoUtils;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @program: ruoyi
 * @description:
 * @author: Chenhenan
 * @create: 2022-04-19 14:28
 **/
@Service
public class WxPayServiceImpl implements WxPayService {

    private static final Logger log = LoggerFactory.getLogger(WxPayServiceImpl.class);
    private final ReentrantLock lock = new ReentrantLock();

    @Autowired
    private WxPayConfig wxPayConfig;
    @Autowired
    private CloseableHttpClient httpClient ;


    @Autowired
    private TransferBatchesMapper transferBatchesMapper;

    /**
     * 转账到零钱
     * @param requestDto
     * @return 批单单号
     * @throws Exception
     */
    @Override
    public void payToUserPurse( PayToUserPurseRequest requestDto )throws Exception{

        log.info("转账到零钱 ===> {}",requestDto);

        if(requestDto.getTotal_amount().compareTo(new BigDecimal(0)) < 1){
            throw new GlobalException("转账总额小于等于零");
        }
        if(requestDto.getTotal_num() <= 0){
            throw new GlobalException("转账总笔数小于等于零");
        }
        Assert.hasText(requestDto.getBatch_name(),"转账到零钱批次名称为空");
        Assert.hasText(requestDto.getBatch_remark(),"转账到零钱批次备注为空");
        //Assert.hasText(requestDto.getTransfer_scene_id(),"转账使用的转账场景ID为空");
        //requestDto.setOut_batch_no(OrderNoUtils.getBatchNo());上一步设置No.
        requestDto.setAppid(wxPayConfig.getAppid());

        Boolean ifCheckName = false;

        // 检验是否需要传入用户姓名
        for(BatchDetails details:requestDto.getTransfer_detail_list()){
            if(StringUtils.isNotBlank(details.getUser_name()) || details.getTransfer_amount().compareTo(new BigDecimal(200000)) > -1){
                ifCheckName = true;
                break;
            }
        }
        List<TransferBatches> detailList = new ArrayList();

        for(BatchDetails details:requestDto.getTransfer_detail_list()){
            //details.setOut_detail_no(OrderNoUtils.getBatchDetailNo());//上一步设置No.
            if(ifCheckName){
                if(StringUtils.isBlank(details.getUser_name())){
                    throw new GlobalException("收款用户姓名为空！");
                }
            }
            if(StringUtils.isBlank(details.getOpenid())){
                throw new GlobalException("收款人openid为空！");
            }
            if(StringUtils.isBlank(details.getTransfer_remark())){
                throw new GlobalException("单笔转账备注为空！");
            }
            if(details.getTransfer_amount().compareTo(BigDecimal.valueOf(0)) == 0){
                throw new GlobalException("单笔转账金额不能为零！");
            }

            TransferBatches batches = new TransferBatches();
            batches.setBatchNo(requestDto.getOut_batch_no());
            batches.setBatchName(requestDto.getBatch_name());
            batches.setBatchRemark(requestDto.getBatch_remark());
            batches.setTotalAmount(requestDto.getTotal_amount());
            batches.setTotalNum(requestDto.getTotal_num());
            batches.setDetailNo(details.getOut_detail_no());
            batches.setDetailAmount(details.getTransfer_amount());
            batches.setDetailRemark(details.getTransfer_remark());
            batches.setDetailOpenid(details.getOpenid());
            batches.setDetailUserid(details.getUserId());
            batches.setDeviceId(details.getDeviceId());
            batches.setSubsidyId(details.getSubsidyId());
            batches.setDetailUserName(details.getUser_name());
            batches.setDetailStatus(WxBatchDetailState.WAIT_PAY.getType());//详单状态：转账中
            batches.setBatchStatus(WxBatchState.WAIT_PAY.getType());//批单状态：待付款
            detailList.add(batches);
        }
        //先插入数据，以免打款却无记录
        for(TransferBatches bd: detailList){
            //bd.setWxBatchId(wxBatchId);
            //bd.setWxCreateTime(parse);用创建表数据时间代替
            transferBatchesMapper.insertTransferBatches(bd);
        }

        //调用打款API
        String url = wxPayConfig.getDomain().concat(WxApiType.PAY_TO_USER_PURSE.getType());
        HttpPost httpPost = new HttpPost(url);

        //将参数转换成json字符串
        String jsonParams = JSON.toJSONString(requestDto);
        log.info("请求参数 ===> {}" + jsonParams);

        StringEntity entity = new StringEntity(jsonParams,"utf-8");
        entity.setContentType("application/json");//设置请求报文格式
        httpPost.setEntity(entity);//将请求报文放入请求对象
        httpPost.setHeader("Accept", "application/json");//设置响应报文格式

        //完成签名并执行请求，并完成验签
        CloseableHttpResponse response = httpClient.execute(httpPost);

        try {

            //解析响应结果
            String bodyAsString = EntityUtils.toString(response.getEntity());
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                log.info("成功, 打款返回结果 = " + bodyAsString);
            } else if (statusCode == 204) {
                log.info("成功");
            } else {
                Map<String,String> result = JSON.parseObject(bodyAsString, HashMap.class);
                String failReason = "打款异常,code:" + result.get("code")+ ", 原因:" + result.get("message");
                TransferBatches transferBatches = new TransferBatches();
                transferBatches.setBatchNo(requestDto.getOut_batch_no());
                transferBatches.setBatchStatus(WxBatchState.CLOSED.getType());
                transferBatches.setDetailStatus(WxBatchDetailState.FAIL.getType());
                transferBatches.setFailReason(failReason);
                transferBatches.setCloseReason("微信平台转账到零钱接口请求失败！");
                transferBatchesMapper.updateTransferBatchesByBatchNoOrDetailNo(transferBatches);
                throw new RuntimeException(failReason);
            }


            //String wxBatchId = result.get("batch_id");
            /*Date parse = new Date();
            String createTime = result.get("create_time");
            String[] split = createTime.split("\\+");
            String d1 = split[0];
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
            try {
                parse = dateFormat.parse(d1);
                System.out.println(parse);
            } catch (ParseException e) {
                e.printStackTrace();
            }*/



        } finally {
            response.close();
        }
    }


    /**
     * 查询转账到零钱状态
     * @param batchNo
     * @param needQueryDetail
     * @param detailStatus
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> queryBatchsStatus(String batchNo, String needQueryDetail, String detailStatus)throws Exception{
        //String url =  String.format(WxApiType.BATCHES_DETAILS_QUERY.getType(), "BATCH20220926115829E41VBgLM","BATCHDT20220926115829wKBWL7LC");
        String url =  String.format(WxApiType.TRANSFER_BATCHES_QUERY.getType(), batchNo,needQueryDetail,detailStatus);
        log.info("查询地址url===>{}",url);
        url = wxPayConfig.getDomain().concat(url);

        //创建远程Get 请求对象
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");

        //完成签名并执行请求
        CloseableHttpResponse response = httpClient.execute(httpGet);
        Map<String,Object> result = null;
        try {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            int statusCode = response.getStatusLine().getStatusCode();

            if (statusCode == 200) {
                log.info("成功, 查询退款返回结果 = " + bodyAsString);
                result = JSON.parseObject(bodyAsString, HashMap.class);

            } else if (statusCode == 204) {
                log.info("成功");
                result = JSON.parseObject(bodyAsString, HashMap.class);
            } else {
                result = new HashMap<>();
                result = JSONObject.parseObject(bodyAsString, new TypeReference<Map<String, Object>>() {});

                log.info("查询退款异常, 响应码 = " + statusCode+ ", 查询退款返回结果 = " + bodyAsString);
            }
            result.put("statusCode",statusCode);
            System.out.println(result);

        } finally {
            response.close();
        }

        return result;

    }

    public static void main(String[] args) {
        String a = "{\"code\":\"NOT_FOUND\",\"message\":\"记录不存在\"}";
//        ObjectMapper mapper = new ObjectMapper();
//        Map<String, String> map = mapper.readValue(a, new TypeReference<Map<String, String>>(){});
        Map<String, Object> map = JSONObject.parseObject(a, new TypeReference<Map<String, Object>>() {});
        System.out.println(map);
    }

    @Override
    public Map<String, Object> queryBatchDetailStatus(String batchNo,String detailNo)throws Exception{
        String url =  String.format(WxApiType.BATCHES_DETAILS_QUERY.getType(), batchNo, detailNo);
        log.info("查询地址url===>{}",url);
        url = wxPayConfig.getDomain().concat(url);

        //创建远程Get 请求对象
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");

        //完成签名并执行请求
        CloseableHttpResponse response = httpClient.execute(httpGet);
        Map<String, Object> result = null;
        try {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                log.info("成功, 查询打款返回结果 = " + bodyAsString);
            } else if (statusCode == 204) {
                log.info("成功");
            } else {
                throw new RuntimeException("查询打款异常, 响应码 = " + statusCode+ ", 查询退款返回结果 = " + bodyAsString);
            }
            result = JSON.parseObject(bodyAsString, HashMap.class);
            System.out.println(result);
        } finally {
            response.close();
        }
        return result;
    }


}
